﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using JetBrains.Annotations;
using MugenMvvmToolkit.Annotations;
#if TASKSUPPORT
using System.Threading.Tasks;
#endif
using MugenMvvmToolkit.Models;

namespace MugenMvvmToolkit.Interfaces.ViewModels
{
    /// <summary>
    ///     Represents the interface which add validation support to view-model.
    /// </summary>
    public interface IValidatableViewModel : IViewModel
#if !NODATAERROR
, IDataErrorInfo
#endif
#if !NONOTIFYDATAERROR
, INotifyDataErrorInfo
#endif

    {
        /// <summary>
        ///     Gets the collection of validators.
        /// </summary>
        [NotNull]
        IEnumerable<IValidator> Validators { get; }

        /// <summary>
        ///     Gets the mapping of model properties.
        ///   <example>
        ///     <code>
        ///       <![CDATA[
        ///        PropertiesMapping.Add("ModelProperty", new[]{"ViewModelProperty"});
        ///       ]]>
        ///     </code>
        ///   </example>
        /// </summary>
        [NotNull]
        IDictionary<string, ICollection<string>> PropertiesMapping { get; }

        /// <summary>
        ///     Gets the list of properties that will not be validated.
        /// </summary>
        [NotNull]
        ICollection<string> IgnoreProperties { get; }

        /// <summary>
        /// Creates an instance of <see cref="IValidatorContext"/>.
        /// </summary>
        /// <param name="instanceToValidate">The specified instance to validate.</param>
        /// <returns>An instance of <see cref="IValidatorContext"/>.</returns>
        [NotNull]
        IValidatorContext CreateContext([NotNull]object instanceToValidate);

        /// <summary>
        ///     Adds the specified validator.
        /// </summary>
        /// <param name="validator">The specified validator.</param>
        void AddValidator([NotNull]IValidator validator);

        /// <summary>
        ///      Removes the specified validator.
        /// </summary>
        /// <param name="validator">The specified validator.</param>
        bool RemoveValidator([NotNull]IValidator validator);

        /// <summary>
        ///     Adds the specified instance to validate.
        /// </summary>
        /// <param name="instanceToValidate">The specified instance to validate.</param>
        void AddInstance([NotNull]object instanceToValidate);

        /// <summary>
        ///     Removes the specified instance to validate.
        /// </summary>
        /// <param name="instanceToValidate">The specified instance to validate.</param>
        bool RemoveInstance([NotNull]object instanceToValidate);

#if TASKSUPPORT
        /// <summary>
        ///     Updates information about errors in the specified instance.
        /// </summary>
        /// <param name="instanceToValidate">The specified instance to validate.</param>
        [SuppressTaskBusyHandler]
        Task ValidateInstance([NotNull]object instanceToValidate);

        /// <summary>
        ///     Updates information about errors in the specified property.
        /// </summary>
        /// <param name="propertyName">The specified property name.</param>
        [SuppressTaskBusyHandler]
        Task Validate([NotNull]string propertyName);

        /// <summary>
        ///     Updates information about errors.
        /// </summary>
        [SuppressTaskBusyHandler]
        Task ValidateAll();
#else
        /// <summary>
        ///     Updates information about errors in the specified instance.
        /// </summary>
        /// <param name="instanceToValidate">The specified instance to validate.</param>
        IOperationResult ValidateInstance([NotNull]object instanceToValidate);

        /// <summary>
        ///     Updates information about errors in the specified property.
        /// </summary>
        /// <param name="propertyName">The specified property name.</param>
        IOperationResult Validate([NotNull] string propertyName);

        /// <summary>
        ///     Updates information about all errors.
        /// </summary>
        IOperationResult ValidateAll();
#endif

#if !NODATAERROR
        /// <summary>
        ///     Gets the validation errors for a specified property or for the entire entity.
        /// </summary>
        /// <returns>
        ///     The validation errors for the property or entity.
        /// </returns>
        /// <param name="propertyName">
        ///     The name of the property to retrieve validation errors for; or null or <see cref="F:System.String.Empty" />, to retrieve entity-level errors.
        /// </param>
        [NotNull]
        IEnumerable GetErrors([CanBeNull]string propertyName);
#endif
        /// <summary>
        ///     Gets the all validation errors.
        /// </summary>
        /// <returns>
        ///     The validation errors.
        /// </returns>
        [NotNull]
        IDictionary<string, IList<object>> GetAllErrors();

        /// <summary>
        ///     Clears errors for a property.
        /// </summary>
        /// <param name="propertyName">The name of the property</param>
        void ClearErrors([NotNull]string propertyName);

        /// <summary>
        ///     Clears the all errors.
        /// </summary>
        void ClearErrors();

        /// <summary>
        ///     Determines whether the current view model is valid.
        /// </summary>
        /// <returns>
        ///     If <c>true</c> current view model is valid, otherwise <c>false</c>.
        /// </returns>
        [Pure]
        bool IsValid();
    }
}